﻿/******************************************************************************
 * 【本类功能概述】                                 					      *
 *  版权所有（C）2017-20XX，匠梦科技                                         *
 *  保留所有权利。                                                            *
 ******************************************************************************
 *  作者 : <hughjk>
 *  创建时间:2019年5月19日 14:59:28
 *  文件描述:扩展代码
 *****************************************************************************/

using System;
using System.Collections.Generic;
using System.Text;

namespace Util
{
    public static partial class StringTool
    {
        public enum bType
        {
            Int,
            Float,
            String,
        }

        public static bType toType(this string s)
        {
            int d = 0;
            bool isint = true;
            if (s.Length <= 0)
            {
                isint = false;
            }
            for (int i = 0; i < s.Length; i++)
            {
                if (((s[i] >= '0' && s[i] <= '9') || s[i] == '-') == false)
                {
                    if (s[i] == '.' && d == 0)
                    {
                        d++;
                    }
                    else
                    {
                        isint = false;
                        break;
                    }
                }
            }
            if (d == 1 && isint)
            {
                return bType.Float;
            }
            else if (d == 0 && isint)
            {
                return bType.Int;
            }
            else
            {
                return bType.String;
            }
        }

        public static T tolog<T>(this T obj, bool isdebug = true)
        {
            //debug.log(isdebug, obj);
            return obj;
        }

        /// <summary>
        /// 是否为有效串
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool isValid(this string s)
        {
            if (s != null && s.Length > 0)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 是否为空串
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static bool isNull(this string s)
        {
            if (s != null && s.Length > 0)
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 显示类型的状态值为二进制显示
        /// </summary>
        public static string to2s(this int num)
        {
            return Convert.ToString(num, 2);
        }

        private static StringBuilder sb = new StringBuilder();

        public static T toEnum<T>(this string eunm)
        {
            T t = default(T);
            try
            {
                t = (T)(Enum.Parse(typeof(T), eunm));
            }
            catch (System.Exception)
            {
                //debug.log(debug.Level.error_3, "字符串转枚举类似错误!!", eunm, typeof(T));
            }
            return t;
        }

        public static List<string> toGetPinying(this string s)
        {
            List<string> vs = new List<string>();
            foreach (char vChar in s)
            {
                if ((int)vChar >= 19968 && (int)vChar <= 40869)
                {
                    vs.Add(vChar + "");
                }
            }
            return vs;
        }

        //转换字符串并且保留N位小数
        public static string toString(this float v, int len = 2)
        {
            string vs = string.Empty;
            v = v.toRound(len);
            if (len == 0)
            {
                vs = ((int)v).toString();
            }
            else
            {
                vs = string.Format(string.Format("{0}0:F{1}{2}", "{", len, "}"), v);
            }

            return vs;
        }

        /// <summary>
        /// 百分比
        /// </summary>
        public static string toPercentage(this float v, int len = 2)
        {
            v = (v.toRound(len + 2)) * 100;
            return string.Format("{0:F2}%", v);
        }

        /// <summary>
        /// 界面数字字符串,需要正负符号
        /// </summary>
        /// <param name="num"></param>
        /// <returns></returns>
        public static string toUIString(this int num)
        {
            if (num >= 0)
            {
                return string.Format("+{0}", num);
            }
            else
            {
                return num.toString();
            }
        }

        public static string toUIString(this float num)
        {
            if (num >= 0)
            {
                return string.Format("+{0}", num);
            }
            else
            {
                return num.toString();
            }
        }

        public static List<string> toCopy(this string[] s, int str, int end)
        {
            List<string> vs = new List<string>();
            for (int i = str; i < end; i++)
            {
                vs.Add(s[i]);
            }
            return vs;
        }

        public static List<string> toCopy(this List<string> s, int str, int end)
        {
            List<string> vs = new List<string>();
            for (int i = str; i < end; i++)
            {
                vs.Add(s[i]);
            }
            return vs;
        }

        public static string RemoveBracket(this string _str)
        {
            if (_str.Contains("("))
            {
                var pos = _str.IndexOf("(");
                _str = _str.Substring(0, pos);
            }
            else if (_str.Contains("（"))
            {
                var pos = _str.IndexOf("（");
                _str = _str.Substring(0, pos);
            }
            _str = _str.Replace(" ", "");
            return _str;
        }

        public static string RemoveCloneString(this string name)
        {
            bool isClone = true;
            int pos = name.IndexOf("(Clone)");

            if (pos <= 0)
            {
                pos = name.IndexOf("(");
                if (pos > 0)
                {
                    isClone = false;
                }
            }

            if (pos > 0)
            {
                name = name.Substring(0, isClone ? pos : (pos - 1));
            }

            return name;
        }

        /// <summary>
        /// 取其中的几位,并转换为整形
        /// </summary>
        /// <param name="s"></param>
        /// <param name="str">从0开始</param>
        /// <param name="len"></param>
        /// <returns></returns>
        public static int subToInt(this string s, int str, int len)
        {
            string z = s.Substring(str, len);
            return z.toInt();
        }

        private static bool isNumStringPool = false;
        private static Dictionary<int, string> NumStringPool = new Dictionary<int, string>();
        private static Dictionary<long, string> longStringPool = new Dictionary<long, string>();
        private static Dictionary<int, string> TemporaryNumStringPool = new Dictionary<int, string>();

        //适当的时候清空字符串缓存
        public static void ClearTemporaryNumStringPool()
        {
            TemporaryNumStringPool.Clear();
        }

        /// <summary>
        /// 常用数值缓存
        /// </summary>
        public static string toString(this int num)
        {
            if (!isNumStringPool)
            {
                isNumStringPool = true;
                for (int i = -150; i < 150; i++)
                {
                    NumStringPool.Add(i, i.ToString());
                }
            }
            if (num < -150 || num >= 150)
            {
                string s;
                if (TemporaryNumStringPool.Count > 200)
                {
                    TemporaryNumStringPool.Clear();
                }

                if (TemporaryNumStringPool.TryGetValue(num, out s))
                {
                    return s;
                }
                else
                {
                    s = num.ToString();
                    TemporaryNumStringPool.Add(num, s);
                    return s;
                }
            }
            else
            {
                return NumStringPool[num];
            }
        }
        public static string toString(this uint num)
        {
            if (num>=int.MaxValue)
            {
                return toString((long)num);
            }
            else
            {
                return toString((int)num);
            }
        }

        public static string toString(this long num)
        {
            if (!longStringPool.ContainsKey(num))
            {
                longStringPool.Add(num, num.ToString());
            }
            return longStringPool[num];
        }

        /// <summary>
        /// 比较两个对象是否相等
        /// </summary>
        /// <param name="_str"></param>
        /// <param name="_str1"></param>
        /// <returns></returns>
        public static bool StringSame(this string _str, string _str1)
        {
            return string.Compare(_str, _str1, StringComparison.Ordinal) == 0;
        }

        #region 查询关键字方法

        private static int[] GetKmpNext(string pattern)
        {
            int[] next = new int[pattern.Length];
            next[0] = -1;
            if (pattern.Length < 2) return next;
            next[1] = 0;
            int i = 2, j = 0;
            while (i < pattern.Length)
            {
                if (pattern[i - 1] == pattern[j])
                {
                    next[i++] = ++j;
                }
                else
                {
                    j = next[j];
                    if (j == -1)
                    {
                        next[i++] = ++j;
                    }
                }
            }
            return next;
        }

        /// <summary>
        /// 查询关键字 模糊查询 PC测试 "LevenshteinDis";{ "Ls", "La", "Ldd", "asde", "Lfasde", "in" } ,1000次 3毫秒
        /// </summary>
        /// <param name="source">原字符串</param>
        /// <param name="keywords">关键字列表用|分开</param>
        /// <returns>如果存在关键字返回true，反之返回false。</returns>
        public static bool to_find_Key(this string source, string[] keywords)
        {
            int wordCount = keywords.Length;
            int[][] nexts = new int[wordCount][];
            int i = 0;
            for (i = 0; i < wordCount; i++)
            {
                nexts[i] = GetKmpNext(keywords[i]);
            }
            i = 0;
            int[] j = new int[nexts.Length];
            while (i < source.Length)
            {
                for (int k = 0; k < wordCount; k++)
                {
                    if (source[i] == keywords[k][j[k]])
                    {
                        j[k]++;
                    }
                    else
                    {
                        j[k] = nexts[k][j[k]];
                        if (j[k] == -1)
                        {
                            j[k]++;
                        }
                    }
                    if (j[k] >= keywords[k].Length)
                    {
                        return true;
                    }
                }
                i++;
            }
            return false;
        }

        #endregion 查询关键字方法

        #region 字符串匹配度查询

        /// <summary>
        /// 字符串匹配度查询 返回0-1的一个值,1表示完全匹配 PC测试 "LevenshteinDis"; "Levenshte";, 1000次 7毫秒
        /// </summary>
        /// <param name="source"></param>
        /// <param name="str2"></param>
        /// <returns></returns>
        public static float to_similarity(this string str1, string str2)
        {
            return LevenshteinDistance.Ins.LevenshteinDistancePercent(str1, str2);
        }

        /// <summary>
        /// 编辑距离算法
        /// </summary>
        private class LevenshteinDistance
        {
            private static LevenshteinDistance ins = null;

            public static LevenshteinDistance Ins
            {
                get
                {
                    if (ins == null)
                    {
                        return new LevenshteinDistance();
                    }
                    return ins;
                }
            }

            /// <summary>
            /// 取最小的一位数
            /// </summary>
            /// <param name="first"></param>
            /// <param name="second"></param>
            /// <param name="third"></param>
            /// <returns></returns>
            public int LowerOfThree(int first, int second, int third)
            {
                int min = first;
                if (second < min)
                    min = second;
                if (third < min)
                    min = third;
                return min;
            }

            public int Levenshtein_Distance(string str1, string str2)
            {
                int[,] Matrix;
                int n = str1.Length;
                int m = str2.Length;

                int temp = 0;
                char ch1;
                char ch2;
                int i = 0;
                int j = 0;
                if (n == 0)
                {
                    return m;
                }
                if (m == 0)
                {
                    return n;
                }
                Matrix = new int[n + 1, m + 1];

                for (i = 0; i <= n; i++)
                {
                    //初始化第一列
                    Matrix[i, 0] = i;
                }

                for (j = 0; j <= m; j++)
                {
                    //初始化第一行
                    Matrix[0, j] = j;
                }

                for (i = 1; i <= n; i++)
                {
                    ch1 = str1[i - 1];
                    for (j = 1; j <= m; j++)
                    {
                        ch2 = str2[j - 1];
                        if (ch1.Equals(ch2))
                        {
                            temp = 0;
                        }
                        else
                        {
                            temp = 1;
                        }
                        Matrix[i, j] = LowerOfThree(Matrix[i - 1, j] + 1, Matrix[i, j - 1] + 1, Matrix[i - 1, j - 1] + temp);
                    }
                }

                //for (i = 0; i <= n; i++)
                //{
                //    for (j = 0; j <= m; j++)
                //    {
                //        Console.Write(" {0} ", Matrix[i, j]);
                //    }
                //    Console.WriteLine("");
                //}
                return Matrix[n, m];
            }

            /// <summary>
            /// 计算字符串相似度
            /// </summary>
            /// <param name="str1"></param>
            /// <param name="str2"></param>
            /// <returns></returns>
            public float LevenshteinDistancePercent(string str1, string str2)
            {
                float maxLenth = str1.Length > str2.Length ? str1.Length : str2.Length;
                float val = Levenshtein_Distance(str1, str2);
                return 1 - val / maxLenth;
            }
        }

        #endregion 字符串匹配度查询
    }
}